package com.itheima.pinda.config;


import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.itheima.pinda.entity.base.Entity;
import com.itheima.pinda.entity.base.SuperEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;

/**
 * MyBatis Plus 元数据处理类
 * 用于自动 注入 id, createTime, updateTime, createUser, updateUser 等字段
 */
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {


    /**
     * 先默认设置插入用户id为  0
     */
    public static final Long INSERT_USER = 0L;
    /**
     * 先默认设置更新用户id为  2
     */
    public static final Long UPDATE_USER = 2L;

    /**
     * Version常量
     */
    public static final String VERSION = "version";

    /**
     * Version常量默认值
     */
    public static final Integer VERSION_DEFAULT_VALUE = 1;
    /**
     * id类型判断符
     */
    private final static String ID_TYPE = "java.lang.String";

    /**
     * 实体类型判断符
     */
    private CustomIdGenerator idGenerator;

    public MyMetaObjectHandler(CustomIdGenerator idGenerator) {
        super();
        this.idGenerator = idGenerator;
    }

    public MyMetaObjectHandler() {
    }

    /**
     * 所有的继承了Entity、SuperEntity的实体，在insert时，
     * id： 会通过IdGenerate生成唯一ID
     * createUser, updateUser: 自动赋予 当前线程上的登录人id
     * createTime, updateTime: 自动赋予 服务器的当前时间
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill........");
        if (metaObject.getOriginalObject() instanceof Entity) {
            Entity entity = (Entity) metaObject.getOriginalObject();
            if (entity.getCreateTime() == null) {
                this.setFieldValByName(Entity.CREATE_TIME, LocalDateTime.now(), metaObject);
            }
            if (entity.getCreateUser() == null || entity.getCreateUser().equals(0)) {
                // todo 由于这里没有实现BaseContextHandler, 所有这里先用 两个常量值代替创建用户id和更新用户id
                if (ID_TYPE.equals(metaObject.getGetterType(Entity.CREATE_USER).getName())) {
                    this.setFieldValByName(Entity.CREATE_USER, String.valueOf(INSERT_USER), metaObject);
                } else {
                    this.setFieldValByName(Entity.CREATE_USER, INSERT_USER, metaObject);
                }
            }
            update(metaObject, entity);
        }

        if (metaObject.getOriginalObject() instanceof SuperEntity) {
            Object oldId = ((SuperEntity) metaObject.getOriginalObject()).getId();
            if (oldId == null) {
                Long id = idGenerator.idWorker().nextId();
                if (ID_TYPE.equals(metaObject.getGetterType(SuperEntity.FIELD_ID).getName())) {
                    this.setFieldValByName(SuperEntity.FIELD_ID, String.valueOf(id), metaObject);
                } else {
                    this.setFieldValByName(SuperEntity.FIELD_ID, id, metaObject);
                }
            }
        }
    }

    private void update(MetaObject metaObject, Entity entity, String et) {
        if (entity.getUpdateUser() == null || entity.getUpdateUser().equals(0)) {
            if (ID_TYPE.equals(metaObject.getGetterType(et + Entity.UPDATE_USER).getName())) {
                this.setFieldValByName(Entity.UPDATE_USER, String.valueOf(UPDATE_USER), metaObject);
            } else {
                this.setFieldValByName(Entity.UPDATE_USER, UPDATE_USER, metaObject);
            }
        } else {
            // todo 取出当前用户的操作的id
            this.setFieldValByName(Entity.UPDATE_USER, UPDATE_USER, metaObject);
        }
        this.setFieldValByName(Entity.UPDATE_TIME, LocalDateTime.now(), metaObject);
    }

    private void update(MetaObject metaObject, Entity entity) {
        update(metaObject, entity, "");
    }

    /**
     * 所有的继承了Entity、SuperEntity的实体，在update时，
     * updateUser: 自动赋予 当前线程上的登录人id
     * updateTime: 自动赋予 服务器的当前时间
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.debug("start update fill ....");
        if (metaObject.getOriginalObject() instanceof Entity) {
            Entity entity = (Entity) metaObject.getOriginalObject();
            update(metaObject, entity);
        } else {
            //updateById updateBatchById update(T entity, Wrapper<T> updateWrapper);
            Object et = metaObject.getValue(Constants.ENTITY);
            if (et instanceof Entity) {
                Entity entity = (Entity) et;
                update(metaObject, entity, Constants.ENTITY + ".");
            }
        }
    }
}
